package data.email;

import data.Term;
import data.TermCollection;
import data.email.comparator.BodyFieldComparator;
import data.email.comparator.DateFieldComparator;
import data.email.comparator.FromFieldComparator;
import data.email.comparator.SubjectFieldComparator;
import data.email.comparator.ToFieldComparator;
import data.email.comparator.UnionFieldComparator;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.PriorityQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import process.TermRanker;

/**
 * EmailSummaryWriter menuliskan hasil koleksi term ke dalam file
 * @author Robert Gunawan
 */
public class EmailSummaryWriter {

    /**
     * konstruktor dari EmailSummaryWriter
     */
    public EmailSummaryWriter() {
    }

    /**
     * menuliskan file summary
     * @param terms top terms yang dituliskan
     * @param directory direktori tempat file
     * @param labelString label 
     * @param tokenCounter token counter
     */
    private void writeFileSummary(ArrayList<Term> terms, String directory, String labelString, EmailTokenCounter tokenCounter) {
        String nameLabelString = "ali_robert_muqtafi_" + labelString;
        String fileName = directory + File.separator + nameLabelString + ".txt";
        Long termOccurence = new Long(0);
        if (terms.size() > 0) {
            EmailTermCollection termCollection = (EmailTermCollection) terms.get(0).getCollectionRef();
            Integer uniqueTokens = 0;
            if (labelString.equals("from")) {
                uniqueTokens = termCollection.getFromTermCount();
                termOccurence = tokenCounter.getToFromField();
            } else if (labelString.equals("to")) {
                uniqueTokens = termCollection.getToTermCount();
                termOccurence = tokenCounter.getToToField();
            } else if (labelString.equals("subject")) {
                uniqueTokens = termCollection.getSubjectTermCount();
                termOccurence = tokenCounter.getToSubjectField();
            } else if (labelString.equals("date")) {
                uniqueTokens = termCollection.getDateTermCount();
                termOccurence = tokenCounter.getToDateField();
            } else if (labelString.equals("body")) {
                uniqueTokens = termCollection.getBodyTermCount();
                termOccurence = tokenCounter.getToBodyField();
            } else if (labelString.equals("union")) {
                uniqueTokens = termCollection.getUnionCount();
                termOccurence = tokenCounter.getToUnionField();
            }
            try {
                FileWriter fstream = new FileWriter(fileName);
                BufferedWriter out = new BufferedWriter(fstream);
                // mulai menuliskan file
                out.write(nameLabelString + " " + termCollection.getDocumentCount() + "\n"); // menuliskan jumlah dokumen
                out.write(nameLabelString + " " + termOccurence + "\n"); // menuliskan term occurence
                out.write(nameLabelString + " " + uniqueTokens + "\n"); // menuliskan unique tokens
                int iter = 1;
                // menuliskan semua top terms
                for (Term term : terms) {
                    EmailStatistic stat = (EmailStatistic) term.getStatistic();
                    if (labelString.equals("from")) {
                        out.write(nameLabelString + " " + iter + " " + term.getTermString() + " " + stat.getFromTF() + " " + stat.getFromDF() + " " + stat.getFromWeight() + "\n");
                    } else if (labelString.equals("to")) {
                        out.write(nameLabelString + " " + iter + " " + term.getTermString() + " " + stat.getToTF() + " " + stat.getToDF() + " " + stat.getToWeight() + "\n");
                    } else if (labelString.equals("subject")) {
                        out.write(nameLabelString + " " + iter + " " + term.getTermString() + " " + stat.getSubjectTF() + " " + stat.getSubjectDF() + " " + stat.getSubjectWeight() + "\n");
                    } else if (labelString.equals("date")) {
                        out.write(nameLabelString + " " + iter + " " + term.getTermString() + " " + stat.getDateTF() + " " + stat.getDateDF() + " " + stat.getDateWeight() + "\n");
                    } else if (labelString.equals("body")) {
                        out.write(nameLabelString + " " + iter + " " + term.getTermString() + " " + stat.getBodyTF() + " " + stat.getBodyDF() + " " + stat.getBodyWeight() + "\n");
                    } else if (labelString.equals("union")) {
                        out.write(nameLabelString + " " + iter + " " + term.getTermString() + " " + stat.getUnionTF() + " " + stat.getUnionDF() + " " + stat.getUnionWeight() + "\n");
                    }
                    iter++;
                }
                out.close();
                fstream.close();
            } catch (Exception e) {//Catch exception if any
                System.err.println("Error: " + e.getMessage());
            }
        }
    }

    /**
     * menuliskan summary dari term collection yang diberikan
     * @param termCollection term collection
     * @param termCount jumlah top term yang diinginkan
     * @param directory directory penyimpanan file
     * @param tokenCounter token counter
     */
    public void writeSummary(TermCollection termCollection, Integer termCount, String directory, EmailTokenCounter tokenCounter) {
        // create ranker thread for each field
        TermRanker fromRanker = new TermRanker(new PriorityQueue<Term>(100000, new FromFieldComparator()), termCollection);
        Thread fromRankerThread = new Thread(fromRanker);
        TermRanker toRanker = new TermRanker(new PriorityQueue<Term>(100000, new ToFieldComparator()), termCollection);
        Thread toRankerThread = new Thread(toRanker);
        TermRanker subjectRanker = new TermRanker(new PriorityQueue<Term>(100000, new SubjectFieldComparator()), termCollection);
        Thread subjectRankerThread = new Thread(subjectRanker);
        TermRanker dateRanker = new TermRanker(new PriorityQueue<Term>(100000, new DateFieldComparator()), termCollection);
        Thread dateRankerThread = new Thread(dateRanker);
        TermRanker bodyRanker = new TermRanker(new PriorityQueue<Term>(100000, new BodyFieldComparator()), termCollection);
        Thread bodyRankerThread = new Thread(bodyRanker);
        TermRanker unionRanker = new TermRanker(new PriorityQueue<Term>(100000, new UnionFieldComparator()), termCollection);
        Thread unionRankerThread = new Thread(unionRanker);

        // run all rankers
        System.out.println("## Start from ranker");
        fromRankerThread.start();
        System.out.println("## Start to ranker");
        toRankerThread.start();
        System.out.println("## Start subject ranker");
        subjectRankerThread.start();
        System.out.println("## Start date ranker");
        dateRankerThread.start();
        System.out.println("## Start body ranker");
        bodyRankerThread.start();
        System.out.println("## Start union ranker");
        unionRankerThread.start();

        // wait all rankers
        try {
            fromRankerThread.join();
            System.out.println("## End from ranker, writing from label summary");
            writeFileSummary(fromRanker.getTopTerms(termCount), directory, "from", tokenCounter);
        } catch (InterruptedException ex) {
            Logger.getLogger(EmailSummaryWriter.class.getName()).log(Level.SEVERE, null, ex);
        }
        try {
            toRankerThread.join();
            System.out.println("## End to ranker, writing to label summary");
            writeFileSummary(toRanker.getTopTerms(termCount), directory, "to", tokenCounter);
        } catch (InterruptedException ex) {
            Logger.getLogger(EmailSummaryWriter.class.getName()).log(Level.SEVERE, null, ex);
        }
        try {
            subjectRankerThread.join();
            System.out.println("## End subject ranker, writing subject label summary");
            writeFileSummary(subjectRanker.getTopTerms(termCount), directory, "subject", tokenCounter);
        } catch (InterruptedException ex) {
            Logger.getLogger(EmailSummaryWriter.class.getName()).log(Level.SEVERE, null, ex);
        }
        try {
            dateRankerThread.join();
            System.out.println("## End date ranker, writing date label summary");
            writeFileSummary(dateRanker.getTopTerms(termCount), directory, "date", tokenCounter);
        } catch (InterruptedException ex) {
            Logger.getLogger(EmailSummaryWriter.class.getName()).log(Level.SEVERE, null, ex);
        }
        try {
            bodyRankerThread.join();
            System.out.println("## End body ranker, writing body label summary");
            writeFileSummary(bodyRanker.getTopTerms(termCount), directory, "body", tokenCounter);
        } catch (InterruptedException ex) {
            Logger.getLogger(EmailSummaryWriter.class.getName()).log(Level.SEVERE, null, ex);
        }
        try {
            unionRankerThread.join();
            System.out.println("## End union ranker, writing union label summary");
            writeFileSummary(unionRanker.getTopTerms(termCount), directory, "union", tokenCounter);
        } catch (InterruptedException ex) {
            Logger.getLogger(EmailSummaryWriter.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
